From 74026576724defce11d34def23d855de9e699a4d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 18 May 2006 20:09:05 +0000 Subject: [PATCH] Add a GtkPrintOperation:: paginate signal that gets emitted to paginate a 2006-05-18 Matthias Clasen * gtk/gtkprintoperation.h: * gtk/gtkprintoperation.c: Add a GtkPrintOperation:: paginate signal that gets emitted to paginate a document in chunks. --- ChangeLog | 7 ++ ChangeLog.pre-2-10 | 7 ++ gtk/gtkmarshalers.list | 1 + gtk/gtkprintoperation-private.h | 2 + gtk/gtkprintoperation.c | 183 ++++++++++++++++++++++---------- gtk/gtkprintoperation.h | 26 ++--- 6 files changed, 155 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index f40a6d9fbc..c3fdbf95be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2006-05-18 Matthias Clasen + * gtk/gtkprintoperation.h: + * gtk/gtkprintoperation.c: Add a GtkPrintOperation:: paginate signal + that gets emitted to paginate a document in chunks. + + * gtk/gtkprintoperation-private.h: + * gtk/gtkmarshalers.list: Add necessary glue. + * gtk/gtkcalendar.c (gtk_calendar_drag_motion): Don't produce a stuck drag if shift is held. (#341734, Sebastien Bacher) diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index f40a6d9fbc..c3fdbf95be 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,5 +1,12 @@ 2006-05-18 Matthias Clasen + * gtk/gtkprintoperation.h: + * gtk/gtkprintoperation.c: Add a GtkPrintOperation:: paginate signal + that gets emitted to paginate a document in chunks. + + * gtk/gtkprintoperation-private.h: + * gtk/gtkmarshalers.list: Add necessary glue. + * gtk/gtkcalendar.c (gtk_calendar_drag_motion): Don't produce a stuck drag if shift is held. (#341734, Sebastien Bacher) diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list index e081da60dc..7b98c4ddbe 100644 --- a/gtk/gtkmarshalers.list +++ b/gtk/gtkmarshalers.list @@ -26,6 +26,7 @@ BOOLEAN:BOXED,BOXED BOOLEAN:ENUM BOOLEAN:ENUM,DOUBLE BOOLEAN:ENUM,INT +BOOLEAN:OBJECT BOOLEAN:OBJECT,UINT,FLAGS BOOLEAN:OBJECT,INT,INT,UINT BOOLEAN:OBJECT,STRING,STRING,BOXED diff --git a/gtk/gtkprintoperation-private.h b/gtk/gtkprintoperation-private.h index 194122f2da..392ede6562 100644 --- a/gtk/gtkprintoperation-private.h +++ b/gtk/gtkprintoperation-private.h @@ -40,6 +40,8 @@ struct _GtkPrintOperationPrivate gboolean track_print_status; char *pdf_target; + guint print_pages_idle_id; + /* Data for the print job: */ cairo_surface_t *surface; double dpi_x, dpi_y; diff --git a/gtk/gtkprintoperation.c b/gtk/gtkprintoperation.c index 14a2546d77..963aea0261 100644 --- a/gtk/gtkprintoperation.c +++ b/gtk/gtkprintoperation.c @@ -31,6 +31,7 @@ enum { BEGIN_PRINT, + PAGINATE, REQUEST_PAGE_SETUP, DRAW_PAGE, END_PRINT, @@ -99,6 +100,9 @@ gtk_print_operation_finalize (GObject *object) g_free (priv->pdf_target); g_free (priv->job_name); + if (priv->print_pages_idle_id > 0) + g_source_remove (priv->print_pages_idle_id); + G_OBJECT_CLASS (gtk_print_operation_parent_class)->finalize (object); } @@ -260,6 +264,36 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_PRINT_CONTEXT); + /** + * Gtkprintoperation::paginate: + * @operation: the #GtkPrintOperation on which the signal was emitted + * @context: the #GtkPrintContext for the current operation + * + * Gets emitted after the begin-print signal, but before the actual + * rendering starts. It keeps getting emitted until it returns %FALSE. + * + * This signal is intended to be used for paginating the document + * in small chunks, to avoid blocking the user interface for a long + * time. The signal handler should update the number of pages using + * gtk_print_operation_set_n_pages(), and return %TRUE if the document + * has been completely paginated. + * + * If you don't need to do pagination in chunks, you can simply do + * it all in the begin-print handler, and set the number of pages + * from there. + * + * Since: 2.10 + */ + signals[PAGINATE] = + g_signal_new (I_("paginate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkPrintOperationClass, paginate), + _gtk_boolean_handled_accumulator, NULL, + _gtk_marshal_BOOLEAN__OBJECT, + G_TYPE_BOOLEAN, 1, GTK_TYPE_PRINT_CONTEXT); + + /** * GtkPrintOperation::request-page-setup: * @operation: the #GtkPrintOperation on which the signal was emitted @@ -1309,6 +1343,24 @@ increment_page_sequence (PrintPagesData *data) return TRUE; } +static void +print_pages_idle_done (gpointer user_data) +{ + PrintPagesData *data; + GtkPrintOperationPrivate *priv; + + data = (PrintPagesData*)user_data; + priv = data->op->priv; + + g_object_unref (data->print_context); + g_object_unref (data->initial_page_setup); + + g_object_unref (data->op); + g_free (data); + + priv->print_pages_idle_id = 0; +} + static gboolean print_pages_idle (gpointer user_data) { @@ -1323,6 +1375,66 @@ print_pages_idle (gpointer user_data) data = (PrintPagesData*)user_data; priv = data->op->priv; + if (priv->status == GTK_PRINT_STATUS_PREPARING) + { + if (g_signal_has_handler_pending (data->op, signals[PAGINATE], 0, FALSE)) + { + gboolean paginated = FALSE; + g_signal_emit (data->op, signals[PAGINATE], 0, data->print_context, &paginated); + if (!paginated) + goto out; + } + + /* FIXME handle this better */ + if (priv->nr_of_pages == 0) + g_warning ("no pages to print"); + + /* Initialize parts of PrintPagesData that depend on nr_of_pages + */ + if (priv->print_pages == GTK_PRINT_PAGES_RANGES) + { + data->ranges = priv->page_ranges; + data->num_ranges = priv->num_page_ranges; + } + else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT && + priv->current_page != -1) + { + data->ranges = &data->one_range; + data->num_ranges = 1; + data->ranges[0].start = priv->current_page; + data->ranges[0].end = priv->current_page; + } + else + { + data->ranges = &data->one_range; + data->num_ranges = 1; + data->ranges[0].start = 0; + data->ranges[0].end = priv->nr_of_pages - 1; + } + + if (data->op->priv->manual_reverse) + { + data->range = data->num_ranges - 1; + data->inc = -1; + } + else + { + data->range = 0; + data->inc = 1; + } + find_range (data); + + /* go back one page, since we preincrement below */ + data->page = data->start - data->inc; + data->collated = data->collated_copies - 1; + + _gtk_print_operation_set_status (data->op, + GTK_PRINT_STATUS_GENERATING_DATA, + NULL); + + goto out; + } + data->collated++; if (data->collated == data->collated_copies) { @@ -1331,15 +1443,9 @@ print_pages_idle (gpointer user_data) { g_signal_emit (data->op, signals[END_PRINT], 0, data->print_context); - g_object_unref (data->print_context); - g_object_unref (data->initial_page_setup); - cairo_surface_finish (data->op->priv->surface); priv->end_run (data->op, TRUE); - g_object_unref (data->op); - g_free (data); - done = TRUE; goto out; @@ -1391,79 +1497,35 @@ print_pages (GtkPrintOperation *op, GtkPageSetup *initial_page_setup; GtkPrintContext *print_context; int uncollated_copies, collated_copies; - GtkPageRange *ranges; - int num_ranges; PrintPagesData *data; - - if (priv->manual_collation) - { - uncollated_copies = priv->manual_num_copies; - collated_copies = 1; - } - else - { - uncollated_copies = 1; - collated_copies = priv->manual_num_copies; - } + + _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL); print_context = _gtk_print_context_new (op); initial_page_setup = create_page_setup (op); _gtk_print_context_set_page_setup (print_context, initial_page_setup); - _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_PREPARING, NULL); g_signal_emit (op, signals[BEGIN_PRINT], 0, print_context); - - g_return_if_fail (priv->nr_of_pages > 0); - if (priv->print_pages == GTK_PRINT_PAGES_RANGES) - { - ranges = priv->page_ranges; - num_ranges = priv->num_page_ranges; - } - else if (priv->print_pages == GTK_PRINT_PAGES_CURRENT && - priv->current_page != -1) + if (priv->manual_collation) { - ranges = &data->one_range; - num_ranges = 1; - ranges[0].start = priv->current_page; - ranges[0].end = priv->current_page; + uncollated_copies = priv->manual_num_copies; + collated_copies = 1; } else { - ranges = &data->one_range; - num_ranges = 1; - ranges[0].start = 0; - ranges[0].end = priv->nr_of_pages - 1; + uncollated_copies = 1; + collated_copies = priv->manual_num_copies; } - - _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_GENERATING_DATA, NULL); data = g_new0 (PrintPagesData, 1); data->op = g_object_ref (op); data->uncollated_copies = uncollated_copies; data->collated_copies = collated_copies; - data->ranges = ranges; - data->num_ranges = num_ranges; data->initial_page_setup = initial_page_setup; data->print_context = print_context; - data->uncollated = 0; - if (data->op->priv->manual_reverse) - { - data->range = data->num_ranges - 1; - data->inc = -1; - } - else - { - data->range = 0; - data->inc = 1; - } - find_range (data); - - data->page = data->start - data->inc; - data->collated = data->collated_copies - 1; - if (wait) { /* FIXME replace this with a recursive mainloop */ @@ -1475,7 +1537,10 @@ print_pages (GtkPrintOperation *op, } } else - g_idle_add (print_pages_idle, data); + priv->print_pages_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + print_pages_idle, + data, + print_pages_idle_done); } /** @@ -1493,7 +1558,7 @@ print_pages (GtkPrintOperation *op, * @op to obtain some information about the progress of the print operation. * Furthermore, it may use a recursive mainloop to show the print dialog. * See gtk_print_operation_run_async() if this is a problem. - * + * * * FIXME: need an example here * diff --git a/gtk/gtkprintoperation.h b/gtk/gtkprintoperation.h index dd3a4a8617..adcb9a17ac 100644 --- a/gtk/gtkprintoperation.h +++ b/gtk/gtkprintoperation.h @@ -66,18 +66,20 @@ struct _GtkPrintOperationClass { GObjectClass parent_class; - void (*begin_print) (GtkPrintOperation *operation, - GtkPrintContext *context); - void (*request_page_setup) (GtkPrintOperation *operation, - GtkPrintContext *context, - gint page_nr, - GtkPageSetup *setup); - void (*draw_page) (GtkPrintOperation *operation, - GtkPrintContext *context, - gint page_nr); - void (*end_print) (GtkPrintOperation *operation, - GtkPrintContext *context); - void (*status_changed) (GtkPrintOperation *operation); + void (*begin_print) (GtkPrintOperation *operation, + GtkPrintContext *context); + gboolean (*paginate) (GtkPrintOperation *operation, + GtkPrintContext *context); + void (*request_page_setup) (GtkPrintOperation *operation, + GtkPrintContext *context, + gint page_nr, + GtkPageSetup *setup); + void (*draw_page) (GtkPrintOperation *operation, + GtkPrintContext *context, + gint page_nr); + void (*end_print) (GtkPrintOperation *operation, + GtkPrintContext *context); + void (*status_changed) (GtkPrintOperation *operation); /* Padding for future expansion */ void (*_gtk_reserved1) (void); -- 2.30.2